<?php

/**
 * $Horde:  $
 *
 * Copyright 2001-2006 Horde Project (http://www.horde.org/)
 *
 * See the enclosed file LICENSE for license information (ASL). If you
 * did not receive this file, see http://www.horde.org/licenses/asl.php.
 */

/**
 * Sort by item description.
 */
define('GROO_SORT_TITLE', 0);

/**
 * Sort by item add date.
 */
define('GROO_SORT_MOD_DATE', 1);

/**
 * Sort by item category.
 */
define('GROO_SORT_CATEGORY', 2);

/**
 * Sort in ascending order.
 */
define('GROO_SORT_ASCEND', 0);

/**
 * Sort in descending order.
 */
define('GROO_SORT_DESCEND', 1);


/**
 * Groo Base Class.
 *
 * @author  Jon Parise <jon@horde.org>
 * @author  Luciano Ramalho <luciano@ramalho.org>
 * @since   Groo 1.0
 * @package Groo
 */
class Groo {

    /**
     * Retrieves the current user's item list from storage. This function will
     * also sort the resulting list, if requested.
     *
     * @param constant $sortby   The field by which to sort. (GROO_SORT_TITLE,
     *                           GROO_SORT_CATEGORY)
     * @param constant $sortdir  The direction by which to sort.
     *                           (GROO_SORT_ASC, GROO_SORT_TITLE)
     *
     * @return array  A list of the requested items.
     *
     * @see Groo_Driver::listItems()
     */
    function listItems($sortby = GROO_SORT_TITLE,
                       $sortdir = GROO_SORT_ASCEND)
    {
        global $conf, $display_collections;
        $items = array();

        /* Sort the item list. */
        $sort_functions = array(
            GROO_SORT_TITLE => 'ByDesc',
            GROO_SORT_CATEGORY => 'ByCategory'
        );

        foreach ($display_collections as $collection) {
            /* Create a Groo storage instance. */
            $storage = &Groo_Driver::singleton($collection);
            $storage->retrieve();

            /* Retrieve the item list from storage. */
            $newitems = $storage->listItems();
            $items = array_merge($items, $newitems);
        }

        /* Sort the array if we have a sort function defined for this
         * field. */
        if (isset($sort_functions[$sortby])) {
            $prefix = ($sortdir == GROO_SORT_DESCEND) ? '_rsort' : '_sort';
            uasort($items, array('Groo', $prefix . $sort_functions[$sortby]));
        }

        return $items;
    }

    /**
     * Returns the number of items in collections that the current user owns.
     *
     * @return integer  The number of items that the user owns.
     */
    function countItems()
    {
        static $count;
        if (isset($count)) {
            return $count;
        }

        $collections = Groo::listCollections(true, PERMS_ALL);

        $count = 0;
        foreach (array_keys($collections) as $collection) {
            /* Create a Groo storage instance. */
            $storage = &Groo_Driver::singleton($collection);
            $storage->retrieve();

            /* Retrieve the item list from storage. */
            $count += count($storage->listItems());
        }

        return $count;
    }

    /**
     * Retrieves a specific item from storage.
     *
     * @param string $itemlist  The collection to retrieve the item from.
     * @param string $item      The Id of the item to retrieve.
     *
     * @return array  The item.
     */
    function getItem($collection, $item)
    {
        $storage = &Groo_Driver::singleton($collection);
        return $storage->get($item);
    }

    /**
     * Lists all collections a user has access to.
     *
     * @param boolean $owneronly   Only return item lists that this user owns?
     *                             Defaults to false.
     * @param integer $permission  The permission to filter collections by.
     *
     * @return array  The item lists.
     */
    function listCollections($owneronly = false, $permission = PERMS_SHOW)
    {
        $collections = $GLOBALS['groo_shares']->listShares(Auth::getAuth(), $permission, $owneronly ? Auth::getAuth() : null);
        if (is_a($collections, 'PEAR_Error')) {
            Horde::logMessage($collections, __FILE__, __LINE__, PEAR_LOG_ERR);
            return array();
        }

        return $collections;
    }

    /**
     * Returns the default collection for the current user at the specified
     * permissions level.
     */
    function getDefaultCollection($permission = PERMS_SHOW)
    {
        global $prefs;

        $default_collection = $prefs->getValue('default_collection');
        $collections = Groo::listCollections(false, $permission);

        if (isset($collections[$default_collection])) {
            return $default_collection;
        } elseif ($prefs->isLocked('default_collection')) {
            return '';
        } elseif (count($collections)) {
            return key($collections);
        }

        return false;
    }

    /**
     * Comparison function for sorting items by description.
     *
     * @param array $a  Item one.
     * @param array $b  Item two.
     *
     * @return integer  1 if item one is greater, -1 if item two is greater; 0
     *                  if they are equal.
     */
    function _sortByDesc($a, $b)
    {
        return strcasecmp($a['desc'], $b['desc']);
    }

    /**
     * Comparison function for reverse sorting items by description.
     *
     * @param array $a  Item one.
     * @param array $b  Item two.
     *
     * @return integer  -1 if item one is greater, 1 if item two is greater; 0
     *                  if they are equal.
     */
    function _rsortByDesc($a, $b)
    {
        return strcasecmp($b['desc'], $a['desc']);
    }

    /**
     * Comparison function for sorting items by category.
     *
     * @param array $a  Item one.
     * @param array $b  Item two.
     *
     * @return integer  1 if item one is greater, -1 if item two is greater; 0
     *                  if they are equal.
     */
    function _sortByCategory($a, $b)
    {
        return strcasecmp($a['category'] ? $a['category'] : _("Unfiled"),
                          $b['category'] ? $b['category'] : _("Unfiled"));
    }

    /**
     * Comparison function for reverse sorting items by category.
     *
     * @param array $a  Item one.
     * @param array $b  Item two.
     *
     * @return integer  -1 if item one is greater, 1 if item two is greater; 0
     *                  if they are equal.
     */
    function _rsortByCategory($a, $b)
    {
        return strcasecmp($b['category'] ? $b['category'] : _("Unfiled"),
                          $a['category'] ? $a['category'] : _("Unfiled"));
    }

    /**
     * Returns the specified permission for the current user.
     *
     * @since Groo 2.1
     *
     * @param string $permission  A permission, currently only 'max_items'.
     *
     * @return mixed  The value of the specified permission.
     */
    function hasPermission($permission)
    {
        global $perms;

        if (!$perms->exists('groo:' . $permission)) {
            return true;
        }

        $allowed = $perms->getPermissions('groo:' . $permission);
        if (is_array($allowed)) {
            switch ($permission) {
            case 'max_items':
                $allowed = array_reduce($allowed, create_function('$a, $b', 'return max($a, $b);'), 0);
                break;
            }
        }

        return $allowed;
    }

    /**
     * Builds Groo's list of menu items.
     */
    function getMenu($returnType = 'object')
    {
        global $conf, $registry, $print_link;

        require_once 'Horde/Menu.php';

        $menu = &new Menu();
        $menu->add(Horde::applicationUrl('list.php'), _("_List Items"), 'groo.png', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
        if (Groo::getDefaultCollection(PERMS_EDIT) &&
            (!empty($conf['hooks']['permsdenied']) ||
             Groo::hasPermission('max_items') === true ||
             Groo::hasPermission('max_items') > Groo::countItems())) {
            $menu->add(Horde::applicationUrl('isbn.php?actionID=add_item'), _("_Add books"), 'add.png', null, null, null, Util::getFormData('isbn') ? '__noselection' : null);
        }
        if (Groo::getDefaultCollection(PERMS_READ)) {
            $menu->add(Horde::applicationUrl('search.php'), _("_Search"), 'search.png', $registry->getImageDir('horde'));
        }

        if (Auth::getAuth()) {
            $menu->add(Horde::applicationUrl('collections.php'), _("_My Collections"), 'collections.png');
        }

        if ($returnType == 'object') {
            return $menu;
        } else {
            return $menu->render();
        }
    }

}
